using UnityEngine;
using Noise;
using Render;
using System;

public class PerlinTexture : GUITextureNode
{
    public enum Type
    {
        Classic2,
        Improved2,
        Perlin2,
        Perlin3,
        Billowed2,
        Ridged2
    }

    public Type NoiseType;
    
    public float UVScale = 6.0f;
    public float UVShift = 0.0f;
    public float NoiseScale = 0.5f;
    public float NoiseShift = 0.5f;
    public int Octaves = 1;
    public float Lacunarity = 1.92f;
    public float Gain = 0.5f;
    public float Depth = 0.0f;

    protected override Texture2D CreateTexture()
    {
        return Textures.Create2D(GetPixelData(), TextureSize, false, false);
    }

    private uint[] GetPixelData()
    {
        uint[] noise = new uint[TextureSize*TextureSize];
        for (int h=0; h<TextureSize; h++)
            for (int w=0; w<TextureSize; w++)
                noise[(h*TextureSize)+w] = GetPixel(w, h);
        return noise;
    }

    private uint GetPixel(int w, int h)
    {
        float u = (((float)w)+0.5f)/TextureSize;
        float v = (((float)h)+0.5f)/TextureSize;
        float n = GetNoiseSample(u*UVScale+UVShift, v*UVScale+UVShift, Depth*UVScale+UVShift)*NoiseScale+NoiseShift;
        float c = Colors.Saturate(n);
        return Colors.UInt32FromRGBA(c, c, c, 1.0f);
    }

    private float GetNoiseSample(float x, float y, float z)
    {
        switch (NoiseType)
        {
        case Type.Classic2:     return PerlinClassic.Noise2(x, y, Octaves, Lacunarity, Gain);
        case Type.Improved2:    return PerlinImproved.Noise2(x, y, Octaves, Lacunarity, Gain);
        case Type.Perlin2:      return Perlin.Noise2(x, y, Octaves, Lacunarity, Gain);
        case Type.Perlin3:      return Perlin.Noise3(x, y, z, Octaves, Lacunarity, Gain);
        case Type.Billowed2:    return Perlin.Billowed2(x, y, Octaves, Lacunarity, Gain);
        case Type.Ridged2:      return Perlin.Ridged2(x, y, Octaves, Lacunarity, Gain);
        default:                throw new Exception();
        }
    }
}